package cn.well.cloud.generator.action;

import java.io.File;
import java.util.List;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.well.cloud.generator.engine.config.ContextConfig;
import cn.well.cloud.generator.engine.config.DaoConfig;
import cn.well.cloud.generator.engine.config.ModelConfig;
import cn.well.cloud.generator.engine.config.ServiceConfig;
import cn.well.cloud.generator.engine.config.SqlConfig;
import cn.well.cloud.generator.template.SimpleTemplateEngine;
import cn.well.cloud.generator.template.config.GunsTemplateEngine;

import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;

/**
 * 代码生成的抽象配置
 *
 * @author fengshuonan
 * @date 2017-10-28-下午8:22
 */
public abstract class AbstractGeneratorConfig {

    /**
     * mybatis-plus代码生成器配置
     */
    GlobalConfig globalConfig = new GlobalConfig();

    DataSourceConfig dataSourceConfig = new DataSourceConfig();

    StrategyConfig strategyConfig = new StrategyConfig();

    PackageConfig packageConfig = new PackageConfig();

    TemplateConfig templateConfig = new TemplateConfig();

    TableInfo tableInfo = null;

    /**
     * 自定义代码生成器配置
     */
    ContextConfig contextConfig = new ContextConfig();

    SqlConfig sqlConfig = new SqlConfig();

    ModelConfig modelConfig = new ModelConfig();

    DaoConfig daoConfig = new DaoConfig();

    ServiceConfig serviceConfig = new ServiceConfig();

    protected abstract void config();

    /*
     * 自定义config
     */
    public void initConfig() {

        this.modelConfig.setContextConfig(this.contextConfig);
        this.modelConfig.init();

        this.serviceConfig.setContextConfig(this.contextConfig);
        this.serviceConfig.init();

        this.daoConfig.setContextConfig(this.contextConfig);
        this.daoConfig.init();

        // 父菜单名
        if (this.sqlConfig.getParentMenuName() == null) {
            this.sqlConfig.setParentMenuName(this.contextConfig.getParentMenuName());
        }
    }

    public void init() {
        config();
        templateConfig.setController(null);
        
        // 添加文件是否存在验证，如果存在不会重新生成避免误操作后修改内容丢失
        packageConfig.getController();
        // model层会直接覆盖
        // Mapper层 mapper.java不会被覆盖，mapper.xml会被覆盖，任何扩展方法请写到/ext/对应的xml中 
        String daoPath = StrUtil.format(contextConfig.getProjectPath() + daoConfig.getDaoPathTemplate(),
                StrUtil.upperFirst(contextConfig.getBizEnName()));
        File daoFile = FileUtil.file(daoPath);
        // 已经存在，不生成
        if (daoFile.exists()) {
            templateConfig.setMapper(null);
        }

        // service层不会被覆盖
        String servicePath = StrUtil.format(contextConfig.getProjectPath() + serviceConfig.getServicePathTemplate(),
                StrUtil.upperFirst(contextConfig.getBizEnName()));
        // 修改默认模块为用户填写模块
        servicePath = servicePath.replace(contextConfig.getServiceName(), contextConfig.getModuleName());
        File serviceFile = FileUtil.file(servicePath);
        // 已经存在，不生成
        if (serviceFile.exists()) {
            templateConfig.setService(null);
        }
        String implPath = StrUtil.format(contextConfig.getProjectPath() + serviceConfig.getServiceImplPathTemplate(),
               StrUtil.upperFirst(contextConfig.getBizEnName()));
        // 修改默认模块为用户填写模块
        implPath = implPath.replace(contextConfig.getServiceName(), contextConfig.getModuleName());
        File implFile = FileUtil.file(implPath);
        if (implFile.exists()) {
            templateConfig.setServiceImpl(null);
        }
    }

    /**
     * mybatis-plus 生成controller,entity,dao,service代码
     */
    public void doMpGeneration() {
        init();// 初始化mp配置
        AutoGenerator autoGenerator = new AutoGenerator();
        autoGenerator.setGlobalConfig(globalConfig);
        autoGenerator.setDataSource(dataSourceConfig);
        autoGenerator.setStrategy(strategyConfig);
        autoGenerator.setPackageInfo(packageConfig);
        autoGenerator.setTemplate(templateConfig); // 在脚手架的基础上优化
        autoGenerator.execute();
        if (StrUtil.isNotEmpty(templateConfig.getEntity(globalConfig.isKotlin()))) {
            System.out.println("model生成成功:" + contextConfig.getEntityName() + ".java");
        } else {
            System.out.println("model覆盖成功:" + contextConfig.getEntityName() + ".java");
        }

        if (StrUtil.isNotEmpty(templateConfig.getMapper())) {
            System.out.println("Mapper生成成功:" + contextConfig.getEntityName() + "Mapper.java");
        } else {
            System.out.println(contextConfig.getEntityName() + "Mapper.java" + "已经存在，若需要重新生成，请先手动删除");
        }
        if (StrUtil.isNotEmpty(templateConfig.getXml())) {
            System.out.println("MapperXml生成成功:" + contextConfig.getEntityName() + "Mapper.xml");
        } else {
            System.out.println("MapperXml覆盖成功:" + contextConfig.getEntityName() + "Mapper.xml");
        }

        if (StrUtil.isNotEmpty(templateConfig.getService())) {
            System.out.println("service接口生成成功:I" + contextConfig.getEntityName() + "Service.java");
        } else {
            System.out.println("I" + contextConfig.getEntityName() + "Service.java" + "已经存在，若需要重新生成，请先手动删除");
        }
        if (StrUtil.isNotEmpty(templateConfig.getServiceImpl())) {
            System.out.println("serviceImpl生成成功:" + contextConfig.getEntityName() + "ServiceImpl.java");
        } else {
            System.out.println(contextConfig.getEntityName() + "ServiceImpl.java" + "已经存在，若需要重新生成，请先手动删除");
        }
    
        // 获取table信息,用于guns代码生成
        List<TableInfo> tableInfoList = autoGenerator.getConfig().getTableInfoList();
        if (tableInfoList != null && tableInfoList.size() > 0) {
            this.tableInfo = tableInfoList.get(0);
        }
    }

    public void doRestGeneration() {
        GunsTemplateEngine GunsTemplateEngine = new SimpleTemplateEngine();
        GunsTemplateEngine.setContextConfig(contextConfig);
        GunsTemplateEngine.setTableInfo(tableInfo);
        GunsTemplateEngine.restStart();
    }
    
    public void doWebGeneration() {
        GunsTemplateEngine GunsTemplateEngine = new SimpleTemplateEngine();
        GunsTemplateEngine.setContextConfig(contextConfig);
        sqlConfig.setConnection(dataSourceConfig.getConn());
        GunsTemplateEngine.setSqlConfig(sqlConfig);
        GunsTemplateEngine.setTableInfo(tableInfo);
        GunsTemplateEngine.webStart(); 
    }
}
